home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 43
/
Mac Magazin and MacEasy Magazine CD - Issue 43.iso
/
Software
/
Mobiles Büro
/
Newton
/
Newton Entwickler
/
DIL 2.0 Sample Code ƒ
/
SoupDrink-Mac-4
/
SoupDrink.c
< prev
next >
Wrap
Text File
|
1997-04-17
|
21KB
|
697 lines
/*
* File: SoupDrink.c
*
* Contains: Demonstration of the Newton Desktop Integration Libraries (DILs)
* Communication DILs (CDILs) and High Level Frames DILs (FDILs)
*
* This is the MacOS version of SoupDrink.
* For the Windows code, see the file "SOUPDRNK.C".
*
* Nearly all of the DIL code can be found in the file "engine.c".
* The only interesting DIL code in here can be found near the
* top - in SetupPortMenu and InitializePipe
*
* Written by: Rob Langhorne, J. Christopher Bell, and David Fedor
*
* Copyright: © 1995-1997 by Apple Computer, Inc. All rights reserved.
*
* Disclaimer: This is nearly all MacOS-specific code. It is not intended
* to be an example of good MacOS sample code :-) but it works to
* demonstrate & test how the Newton DILs work.
*
*/
#include <Types.h>
#include <memory.h>
#include <Packages.h>
#include <Errors.h>
#include <quickdraw.h>
#include <fonts.h>
#include <dialogs.h>
#include <windows.h>
#include <menus.h>
#include <devices.h>
#include <events.h>
#include <diskinit.h>
#include <OSUtils.h>
#include <resources.h>
#include <toolutils.h>
#include <AppleEvents.h>
#include <Strings.h>
#include <stdio.h>
#define forMac // this is a Macintosh-only source file...
#include "DILCPipe.h"
#include "HLFDIL.h"
#include "AppDialogs.h"
#include "SoupDrink.h"
#include "Engine.h"
/****** Function prototypes *******/
void EventLoop(void) ;
Boolean DoMenuItem(long val) ;
void DoDiskEvents(long dinfo) ;
void DoDeskAccCall(MenuHandle themenu, long theit) ;
void DisableExpertFuncs(void);
void EnableExpertFuncs(void);
/******** Global variables **********/
// UI stuff
MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gTestHandle, gPortHandle, gFuncMenuHandle;
Boolean gQuit; // Flags for application state
int gNumPorts; // how many ports are in our port menu
// Configuration options set through menus
long gWhichPort, // the number in the menu of which port to use
gWhichTool; // Selector for which communications tool to use
Boolean gEncrypt = false, // Toggles for advanced reading and writing
gByteSwap = false,
gUseUnicode = false,
gExpertMode = false;
// the following are globals set in here, used in Engine.c
void *ourPipe;
void *gThisObject; /* This is the only DIL frame active at one time in this app */
int gInputMode; /* drink mode (receive frames) or spit mode (receive strings) */
char gReceivedString[kMAXSTR]; /* received string; used in 'spit mode' */
long gReceivedStringLen; /* received string length (see above) */
char gTempBuffer [256]; /* a global string buffer for input dialogs, etc */
// SetupPortMenu() demonstrates finding the available ports available on your machine.
// Different model MacOS computers have different ports, and the port names can be
// localized into other languages.
//
// The port names are gotten from the Communications Toolbox and placed directly into
// menu items. Note that InitCRM() is not called - that is called by the DILs as part
// of CDInitCDIL(). (Future versions of the DILs might not call it, though - watch
// for more information on this.)
//
// SoupDrink has a "config" menu to which this function adds port names. When it comes
// time to call CDPipeInit, the port name is taken directly out of the menu.
//
// The basis for this routine was stolen from:
// http://dev.info.apple.com/source/code/Snippets/Communications_Toolbox/FindSerialPorts/ReadMe.html
#include <CommResources.h>
#include <CRMSerialDevices.h>
void SetupPortMenu()
{
CRMRec c;
CRMRecPtr cPtr = &c;
CRMSerialPtr serialPtr;
gNumPorts = 0;
c.crmDeviceType = crmSerialDevice;
c.crmDeviceID = 0;
while (cPtr != nil) {
cPtr = (CRMRecPtr)CRMSearch(&c);
if (cPtr) {
serialPtr = (CRMSerialPtr)cPtr->crmAttributes;
AppendMenu(gPortHandle, *(serialPtr->name)); // this is a Pascal-style string, which is what AppendMenu wants.
gNumPorts++;
c.crmDeviceID = cPtr->crmDeviceID;
}
}
gWhichPort = kFirstPortItem; // default to the first port in the list
if (gNumPorts)
CheckItem(gPortHandle, gWhichPort, true); // put a checkmark next to it.
}
/*
* InitializePipe
*
* Purpose: This function sets up port options for the CDIL function called CDPipeInit.
*
* Note that if you do not "dispose" of the connection, the port can be locked and you will
* get the "port busy" error which will make life difficult for both you and users. It would
* be best if the function which Initializes the pipe takes responsibility for disposing of
* of the pipe.
*/
OSErr InitializePipe ()
{
OSErr fErr;
char Port[100];
// Copy the text for the port right out of the menu item.
// It'll look like "Modem Port" but could be localized into another language!
getitem(gPortHandle, gWhichPort, Port);
switch (gWhichTool) {
case kSerialTool:
fErr = CDPipeInit(ourPipe, "Serial","","Baud 38400 dataBits 8 Parity None Port ", Port, kDefaultBufferSize, kDefaultBufferSize);
break;
case kModemTool:
fErr = CDPipeInit(ourPipe, "Modem","","ModemType \"Newton Serial Connection\" dataBits 8 Parity None Baud 38400 Port ", Port, kDefaultBufferSize, kDefaultBufferSize);
break;
case kADSPTool:
fErr = CDPipeInit(ourPipe, "ADSP","My Desktop Mac","LocalADSPType \"SoupDrink\" RegisterName 1 LocalADSPName ", Port, kDefaultBufferSize, kDefaultBufferSize);
break;
case kIRTool:
fErr = CDPipeInit(ourPipe, "IR","","", Port, kDefaultBufferSize, kDefaultBufferSize);
break;
}
return fErr;
}
void ListenCallback( CommErr errorValue, long refCon )
// This is only used by the "expert" mode, to test asynchronous listening...
{
long length=5;
if (errorValue)
PostAlertMessage("CDPipeAccept asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
else {
errorValue = CDPipeAccept(ourPipe) ;
if (errorValue)
PostAlertMessage("CDPipeAccept asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
else {
errorValue = CDPipeWrite(ourPipe, (void *)"asdf\4", &length, true,0,0,600,0,0); // will generate an error on the Newton side
if (errorValue)
PostAlertMessage("CDPipeWrite asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
}
}
}
/*
* encryptProc
*
* encryptProc is the encryption callback function
*/
static void encryptProc ( void *pData, Size Count, long refCon )
{
Str255 refConStr;
char * localStr;
localStr = (char *) NewPtrClear(Count + 1);
if (!localStr)
return;
strcpy(localStr, (char *)pData);
sprintf((char*) refConStr, "%d", refCon);
PostAlertMessage("We have encrypted:", (char*) localStr, " Reference constant: ", (char*) refConStr);
}
/*
* decryptProc
*
* decryptProc is the decryption callback function
*/
static void decryptProc ( void *pData, Size Count, long refCon )
{
Str255 refConStr;
char * localStr;
localStr = (char *)NewPtrClear(Count + 1);
if (!localStr)
return;
strcpy(localStr,(char *) pData);
NumToString(Count, (unsigned char*) gTempBuffer);
sprintf((char*) refConStr, "%d", refCon);
PostAlertMessage("We have encrypted:", localStr, "Reference constant: ",(char*) refConStr);
}
/* StateStrings
*
* Purpose: return state string based on state number from the CDILs
* (as a pascal string)
* note, if theErr is greater than 50, it is a user CDIL error
*/
char* StateStrings(int theState, Str255 theString)
{
char* s;
char theNum[128];
switch (theState) {
case kCDIL_Uninitialized: s = "CDIL is uninitialized."; break;
case kCDIL_InvalidConnection: s = "CDIL tried to bring up connection, but it failed."; break;
case kCDIL_Disconnected: s = "CDIL is disconnected."; break;
case kCDIL_Listening: s = "CDIL is listening for a connection."; break;
case kCDIL_ConnectPending: s = "A CDIL connection is pending."; break;
case kCDIL_Connected: s = "CDIL is connected."; break;
case kCDIL_Busy: s = "CDIL is busy (either reading or writing)."; break;
case kCDIL_Aborting: s = "CDIL is aborting."; break;
case kCDIL_Startup: s = "CDIL is starting up."; break;
default: s = (theState < 50) ? "Unknown CDIL state." : "(User-defined CDIL state)";
};
strcpy((char*) theString, s);
strcat((char*) theString, ": State #");
NumToString(theState, (unsigned char*) theNum);
strcat((char*) theString, (char*) p2cstr((unsigned char*)theNum));
return (( char*) theString);
}
/*
* Main
*
* This is the entry point for this application.
*/
void main(void)
{
CommErr fErr;
CursHandle W; /* Cursor handle to get cursors */
DialogPtr splash; /* For use in splash screen */
Handle MyMenu; /* my menu bar handle */
Cursor myWatchCursor ; /* The watch "busy" cursor */
#ifdef DEFINE_QD
// This is needed for some compilers...
QDGlobals qd;
#endif
/* Start out with the standard Macintosh initializations */
MaxApplZone();
InitGraf((Ptr)&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
MoreMasters();
MoreMasters();
MoreMasters();
fErr = CDInitCDIL() ;
if (fErr) {
PostAlertMessage("Error initializing CDIL", ErrorStrings((int) fErr, gTempBuffer), "", "");
return;
}
// Initialize the libraries themselves (does not make a connection)
fErr = FDInitFDIL();
if (fErr) {
PostAlertMessage("Error initializing FDIL", ErrorStrings((int) fErr, gTempBuffer), "", "");
return;
}
// Set up the menus
MyMenu = GetNewMBar(kMBarID);
SetMenuBar(MyMenu);
gAppleMenuHandle = GetMenuHandle(kAppleMenu);
gFileMenuHandle = GetMenuHandle(kFileMenu);
gEditMenuHandle = GetMenuHandle(kEditMenu);
gTestHandle = GetMenuHandle(kTestMenu);
gPortHandle = GetMenuHandle(kPortMenu);
gFuncMenuHandle = GetMenuHandle(kFnMenu);
// add desk accessories to the apple menu
AppendResMenu(gAppleMenuHandle, 'DRVR');
SetupPortMenu();
if (gNumPorts==0){
PostAlertMessage("Error getting serial port names", "", "", "");
return;
}
CheckItem(gPortHandle, kSerialTool, false);
CheckItem(gPortHandle, kModemTool, true); // default to the modem tool
CheckItem(gPortHandle, kADSPTool, false);
CheckItem(gPortHandle, kIRTool, false);
gWhichTool = kModemTool;
DisableExpertFuncs();
DrawMenuBar();
// Turn on the watch cursor while the splash screen is showing
W = GetCursor (watchCursor);
if (W)
myWatchCursor = **W;
SetCursor((CursPtr)&myWatchCursor);
ShowCursor();
ShowSplash(&splash);
ourPipe = CDCreateCDILObject();
if (!ourPipe) {
PostAlertMessage("Error instantiating CDIL", "", "", "");
return;
}
HideSplash(splash);
HideCursor();
SetCursor((const Cursor *)&qd.arrow);
ShowCursor();
EventLoop ();
fErr = CDPipeDisconnect (ourPipe);
CDDisposeCDILObject( ourPipe ) ;
CDDisposeCDIL() ;
#ifdef useASLM
CleanupLibraryManager();
#endif
}
/*
* EventLoop
*
* Purpose: This is the main Macintosh event loop processor.
* This function must handle any type of Macintosh event
* like mouse clicks and keyboard events.
*/
void EventLoop ( void )
{
EventRecord gERecord; /* Current Macintosh Toolbox event record */
WindowPtr twindow;
short part;
do {
CDIdle(ourPipe);
WaitNextEvent(everyEvent, &gERecord, 30, nil);
switch (gERecord.what) {
case mouseDown:
/* first see where the hit was */
part = FindWindow(gERecord.where, &twindow);
switch (part) {
case inDesk: /* if they hit in desk, then the process manager */
break; /* will switch us out, we don't need to do anything */
case inMenuBar:
DoMenuItem(MenuSelect(gERecord.where));
break;
case inSysWindow: /* pass to the system */
SystemClick(&gERecord, twindow);
break;
case inContent: /* This app doesn't do windows */
case inDrag:
case inGrow:
case inGoAway:
case inZoomIn:
case inZoomOut:
break;
}
break;
case keyUp: /* don't care */
case mouseUp: /* don't care */
case networkEvt: /* don't care */
case driverEvt: /* don't care */
case kHighLevelEvent: /* AppleEvents */
break;
case keyDown:
case autoKey:
if (gERecord.modifiers & cmdKey)
DoMenuItem(MenuKey((short)(gERecord.message & charCodeMask)));
else
SysBeep(2);
break;
case diskEvt:
/* We don't do anything special for disk events, this just passes them
* to a function that checks for an error on the mount
*/
DoDiskEvents((long)gERecord.message);
break;
default:
break;
}
} while (gQuit != true);
}
/*
* DoDeskAccCall
*
* DoDeskAccCall opens the requested DA
*/
void DoDeskAccCall(MenuHandle themenu, long theit)
{
Str255 DAname;
GetMenuItemText(themenu, (short)theit, DAname);
OpenDeskAcc(DAname);
} /* end DoDeskAccCall */
/*
* DoDiskEvents
*
* DoDiskEvents performs disk mount operations
*/
void DoDiskEvents(long dinfo) /* hi word is error code, lo word is drive number */
{
short theHighWord, theLowWord, hdl;
Point mountpoint = {
40, 40
};
theHighWord = HiWord(dinfo);
theLowWord = LoWord(dinfo);
if (theHighWord != noErr)/* something happened */ {
hdl = DIBadMount(mountpoint, dinfo);
}
}
/*
* DoMenuItem
*
* DoMenuItem processes a menu event
*/
Boolean DoMenuItem(long val)
{
short theLowWord, theHighWord;
CommErr fErr = 0;
Str255 stateString;
CDIL_State state;
theLowWord = LoWord(val);
theHighWord = HiWord(val);
switch (theHighWord) { /* switch off the menu number selected */
case kAppleMenu: /* Apple menu */
if (theLowWord != 1) /* if this was not About, it's a DA */
DoDeskAccCall(gAppleMenuHandle, theLowWord);
else
Alert(kAboutDialog, nil); /* do about box */
break;
case kFileMenu: /* File menu */
gQuit = true; /* only edit item */
break;
case kEditMenu: /* don't care */
SysBeep(1); /* in this release, we don't do anything */
break;
case kTestMenu: /* Test suites */
switch(theLowWord) {
case kSoupDrinkItem:
fErr = SoupDrink();
if (fErr)
PostAlertMessage("Error from Soup Drink", ErrorStrings((int) fErr, gTempBuffer), "", "");
break;
case kNewNameItem: /* Create a new Names Soup entry on the Newton */
fErr = UploadNewName();
if (fErr)
PostAlertMessage("Error from UploadNewName", ErrorStrings((int) fErr, gTempBuffer), "", "");
break;
default: /* Sanity check. Shouldn't get here */
SysBeep(1); /* in this release, we don't do anything */
break;
}
break;
case kPortMenu: // Choose a port…
switch(theLowWord) {
case kSerialTool:
case kModemTool:
case kADSPTool:
case kIRTool:
CheckItem(gPortHandle, kSerialTool, (theLowWord==kSerialTool));
CheckItem(gPortHandle, kModemTool, (theLowWord==kModemTool));
CheckItem(gPortHandle, kADSPTool, (theLowWord==kADSPTool));
CheckItem(gPortHandle, kIRTool, (theLowWord==kIRTool));
gWhichTool = theLowWord;
break;
default: {
int i;
for (i=0; i<gNumPorts; i++)
CheckItem(gPortHandle, kFirstPortItem + i, (theLowWord== kFirstPortItem + i));
gWhichPort = theLowWord;
break;
}
}
break;
case kFnMenu: // Choose a function …
switch(theLowWord) {
case kFInitItem:
fErr = InitializePipe();
if (fErr)
PostAlertMessage("InitializePipe returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
break;
case kFListenItem:
fErr = CDPipeListen(ourPipe, kDefaultTimeout, (CDILCompletionProcPtr)ListenCallback, 0) ;
if (fErr)
PostAlertMessage("CDPipeListen returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
break;
case kFAcceptItem:
fErr = CDPipeAccept(ourPipe) ;
if (fErr)
PostAlertMessage("CDPipeAccept returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
break;
case kFAbortItem:
fErr = CDPipeAbort(ourPipe, kAllPipes) ;
if (fErr)
PostAlertMessage("CDPipeAbort returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
break;
case kFDiscItem:
fErr = CDPipeDisconnect(ourPipe) ;
if (fErr)
PostAlertMessage("CDPipeDisconnect returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
break;
case kFReadItem:
SysBeep(1); /* in this release, we don't do anything */
break;
case kFCountItem:
SysBeep(1); /* in this release, we don't do anything */
break;
case kFWriteItem:
SysBeep(1); /* in this release, we don't do anything */
break;
case kFGetStateItem:
state = CDGetPipeState(ourPipe);
PostAlertMessage("Current state:", StateStrings(state, stateString), "", "");
break;
case kFSetStateItem: /* Set State number (for example, kCDIL_Busy) */
SysBeep(1); /* in this release, we don't do anything */
break;
case kToggleEncryption:
if (gEncrypt) {
CDEncryptFunction(ourPipe, (CDILEncryptionProcPtr) nil, 0 ) ;
CDDecryptFunction(ourPipe, (CDILDecryptionProcPtr) nil, 0 ) ;
gEncrypt = false ;
}
else {
CDEncryptFunction(ourPipe, (CDILEncryptionProcPtr) encryptProc, 100 ) ;
CDDecryptFunction(ourPipe, (CDILDecryptionProcPtr) decryptProc, 100 ) ;
gEncrypt = true ;
}
CheckItem(gFuncMenuHandle, kToggleEncryption, gEncrypt);
break;
case kToggleByteSwap:
if (gByteSwap)
gByteSwap = false ;
else
gByteSwap = true ;
CheckItem(gFuncMenuHandle, kToggleByteSwap, gByteSwap);
break;
case kToggleUnicode:
if (gUseUnicode)
gUseUnicode = false ;
else
gUseUnicode = true ;
CheckItem(gFuncMenuHandle, kToggleUnicode, gUseUnicode);
break;
case kExpertModeToggle:
if (gExpertMode) {
gExpertMode = false ;
DisableExpertFuncs();
}
else {
gExpertMode = true ;
EnableExpertFuncs();
}
CheckItem(gFuncMenuHandle, kExpertModeToggle, gExpertMode);
break;
default:
SysBeep(1); // Sanity check; shouldn't get here
break;
}
}
HiliteMenu(0); // Unhilite the menu label itself
return noErr;
} /* end DoMenuItem */
void EnableExpertFuncs(void) {
EnableItem(gFuncMenuHandle,kFInitItem);
EnableItem(gFuncMenuHandle,kFListenItem);
EnableItem(gFuncMenuHandle,kFAcceptItem);
EnableItem(gFuncMenuHandle,kFAbortItem);
EnableItem(gFuncMenuHandle,kFDiscItem);
// in this release, these items are not supported...
//EnableItem(gFuncMenuHandle,kFReadItem);
//EnableItem(gFuncMenuHandle,kFCountItem);
//EnableItem(gFuncMenuHandle,kFWriteItem);
//EnableItem(gFuncMenuHandle,kFSetStateItem);
EnableItem(gFuncMenuHandle,kToggleEncryption);
EnableItem(gFuncMenuHandle,kToggleByteSwap);
EnableItem(gFuncMenuHandle,kToggleUnicode);
}
void DisableExpertFuncs(void) {
DisableItem(gFuncMenuHandle,kFInitItem);
DisableItem(gFuncMenuHandle,kFListenItem);
DisableItem(gFuncMenuHandle,kFAcceptItem);
DisableItem(gFuncMenuHandle,kFAbortItem);
DisableItem(gFuncMenuHandle,kFDiscItem);
DisableItem(gFuncMenuHandle,kFReadItem);
DisableItem(gFuncMenuHandle,kFCountItem);
DisableItem(gFuncMenuHandle,kFWriteItem);
DisableItem(gFuncMenuHandle,kFSetStateItem);
DisableItem(gFuncMenuHandle,kToggleEncryption);
DisableItem(gFuncMenuHandle,kToggleByteSwap);
DisableItem(gFuncMenuHandle,kToggleUnicode);
}
long CurrentTimeInSeconds()
// return something indicating what time it is, in seconds units
// This is only used to compare one time against another; it does
// not need to have any relationship to the time of day.
{
return (TickCount() / 60);
}